﻿using Cofe.Core;
using Cofe.Core.Actions;
using Cofe.Core.Entry;
using Cofe.Core.Filter;
using Cofe.Core.Interfaces;
using Cofe.Core.Logger;
using Cofe.Core.Property;
using Cofe.Core.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace Cofe.Core
{
    public static class EntryFE
    {

        #region Copy/Move/LinkAsync

        public static Task<ICofeSystemInfo> RenameAsync(ICofeSystemInfo src, string newName,
           IProgress<ProgressEventArgs> progress, CancellationToken cts)
        {
            return CofeServices.TransferManager.RenameAsync(src, src.Parent, newName, progress, cts);
        }

        public static Task<ICofeSystemInfo> CopyAsync(ICofeSystemInfo src, ICofeDirectoryInfo destDirectory,
            IProgress<ProgressEventArgs> progress, CancellationToken cts)
        {
            return CofeServices.TransferManager.TransferAsync(TransferMode.Copy, src, src.Parent, destDirectory, progress, cts);
        }

        public static Task<ICofeSystemInfo> MoveAsync(ICofeSystemInfo src, ICofeDirectoryInfo destDirectory,
            IProgress<ProgressEventArgs> progress, CancellationToken cts)
        {
            return CofeServices.TransferManager.TransferAsync(TransferMode.Move, src, src.Parent, destDirectory, progress, cts);
        }

        public static Task<ICofeSystemInfo> LinkAsync(ICofeSystemInfo src, ICofeDirectoryInfo destDirectory,
           IProgress<ProgressEventArgs> progress, CancellationToken cts)
        {
            return CofeServices.TransferManager.TransferAsync(TransferMode.Link, src, src.Parent, destDirectory, progress, cts);
        }

        public static Task<ICofeSystemInfo[]> LinkAsync(ICofeSystemInfo[] src, ICofeDirectoryInfo destDirectory,
          IProgress<ProgressEventArgs> progress, CancellationToken cts)
        {            
            return CofeServices.TransferManager.TransferAsync(TransferMode.Link, src, src[0].Parent, destDirectory, progress, cts);
        }

        #endregion

        #region SearchAsync

        public static async Task<IAutoEntryList> SearchAsync(string filterStr, bool callSearch = true)
        {
            IAutoEntryList retVal = await TryParsePathAsync<IAutoEntryList>(filterStr, ParsableType.FilterString);
            if (retVal == null)
                throw new NotSupportedException("Search is not supported.");

            if (callSearch)
                await retVal.SearchAsync();

            return retVal;
        }

        public static async Task<IAutoEntryList> SearchAsync(FilterCollections filters, bool callSearch = true)
        {
            IAutoEntryList retVal = CofeServices.EntryListRegistrar.CreateAutoEntryList(filters.EntryFilters, filters.OptionFilters);

            if (callSearch)
                await retVal.SearchAsync();

            return retVal;
        }

        #endregion

        #region Try/ParsePathAsync/Exists

        public static async Task<T> TryParsePathAsync<T>(string path,
            ParsableType type = ParsableType.AutoDetect,
            EntryConstructionFlags flags = EntryConstructionFlags.Default) where T : ICofeSystemInfo
        {
            IPropertyHost pHost = await CofeServices.PathParserManager.Behaviors.TryParsePathAsync(path, type, flags);
            if (pHost == null)
                return default(T);
            else return await CofeServices.EntryConstructor.ConstructEntryAsync<T>(pHost);
        }

        public static async Task<ICofeSystemInfo> TryParsePathAsync(string path,
            ParsableType type = ParsableType.AutoDetect,
            EntryConstructionFlags flags = EntryConstructionFlags.Default)
        {
            IPropertyHost pHost = await CofeServices.PathParserManager.Behaviors.TryParsePathAsync(path, type, flags);
            if (pHost == null)
                return null;
            else return await CofeServices.EntryConstructor.ConstructEntryAsync(pHost);
        }

        public static async Task<T> ParsePathAsync<T>(string path,
            ParsableType type = ParsableType.AutoDetect,
            EntryConstructionFlags flags = EntryConstructionFlags.Default) where T : ICofeSystemInfo
        {
            var retVal = await TryParsePathAsync<T>(path, type, flags);
            if (retVal == null) throw new System.IO.FileNotFoundException(path);
            else return retVal;
        }

        public static async Task<ICofeSystemInfo> ParsePathAsync(string path,
            ParsableType type = ParsableType.AutoDetect,
            EntryConstructionFlags flags = EntryConstructionFlags.Default)
        {
            var retVal = await TryParsePathAsync(path, type, flags);
            if (retVal == null) throw new System.IO.FileNotFoundException(path);
            else return retVal;
        }

        public static Task<T> TryParsePathUncachedAsync<T>(string path) where T : ICofeSystemInfo
        {
            return TryParsePathAsync<T>(path, ParsableType.ParsePathLookup, EntryConstructionFlags.DefaultWithoutCache);
        }

        public static Task<ICofeSystemInfo> TryParsePathUncachedAsync(string path)
        {
            return TryParsePathAsync(path, ParsableType.ParsePathLookup, EntryConstructionFlags.DefaultWithoutCache);
        }

        public static bool Exists(string entryPath)
        {
            var entry = (EntryFE.TryParsePathUncachedAsync(entryPath)).Result;
            return entry != null;
        }

        #endregion
    }
}
